#pragma once

#include <iostream>
#include <cerrno>
#include "Connection.hpp"
#include "logmsg.pb.h"
#include "../../logs/log.h"
#include "Protocol.hpp"
const static int buffer_size = 1024;
class HandlerConnection
{
public:
    static void HandlerRequest(Connection *conn)
    {
        std::string &inbuffer = conn->Inbuffer();
        std::string message;
        // 考虑数据粘包问题
        // 进行自定义协议处理
        while (Protocol::Decode(inbuffer, &message)) // 失败了就是没有完整的报文
        {
            // message 一定有一个完整的报文
            // std::cout << message << std::endl;
            // 2. 反序列化
            log_msg::LogRequest req;
            if (!req.ParseFromString(message))
                continue;
            std::cout << "host_id: " << req.hostid() << ", log_msg #: " << req.msg();
            // 3.业务处理(写入到不同的文件)
            // 这里的写入操作可以优化，异步写入，先将消息存储到缓冲区，然后再去写，避免频繁的打开文件进行读写
            // 创建目录
            std::string pathname;
            // ./UID/
            pathname = "./" + req.hostid() + "/test.log";
            logs::util::File::createDirectory(logs::util::File::getPath(pathname));
            std::ofstream ofs;
            ofs.open(pathname, std::ios::app | std::ios::binary);
            if (ofs.is_open())
                ofs << req.msg();
            else
                ERROR("文件打开失败！");
            // 4.构建响应(对结果进行序列化)
            std::string responseStr;
            // 构建响应
            log_msg::LogRespond resp;
            if (ofs.good())
                resp.set_success(true);
            else
            {
                resp.set_success(false);
                resp.set_err_message(strerror(errno));
            }
            // 写完注意关闭文件，避免资源泄漏
            ofs.close();
            resp.SerializeToString(&responseStr);
            // 5. encode 封装完整报文
            responseStr = Protocol::Encode(responseStr);
            // 6. 将应答添加到outbuffer中
            conn->AddOutbuffer(responseStr);
        }
        // 考虑发送的问题
        if (!conn->OutBufferEmpty())
        {
            conn->_sender(conn); // 对写事件, 直接发
        }
    }
    // 这里读取的时候, 我们关心的数据是什么格式?协议是什么样的?
    // 不关心!!!这里只需要要负责把本轮数据读取完毕 -- 读到的字节流数据交给上层 -- 有上层分析处理
    static void Recver(Connection *conn) // 读取并处理
    {
        // DEBUG("调用读方法! sockfd: %d", conn->SockFd());
        errno = 0;
        char buffer[buffer_size];
        while (true)
        {
            ssize_t n = recv(conn->SockFd(), buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                conn->AddInbuffer(buffer);
            }
            else
            {
                if (errno == EAGAIN)
                    break;
                else if (errno == EINTR)
                    continue; // 信号中断
                else
                {
                    conn->_excepter(conn); // 直接回调自己的异常处理即可
                    return;
                }
            }
        }
        // 分析处理报文
        HandlerRequest(conn);
    }

    static void Sender(Connection *conn)
    {
        errno = 0;
        std::string &outbuffer = conn->Outbuffer();
        while (true)
        {
            ssize_t n = send(conn->SockFd(), outbuffer.c_str(), outbuffer.size(), 0);

            if (n >= 0)
            {
                outbuffer.erase(0, n); // 已经发给OS的，就直接移除了 // conn->remove(n);
                if (outbuffer.empty())
                    break;
            }
            else
            {
                if (errno == EAGAIN)
                    break; // 只有这里，才会正常退出
                else if (errno == EINTR)
                    continue;
                else
                {
                    conn->_excepter(conn);
                    return;
                }
            }
        }

        // 走到这里，意味着什么？我们本轮发满了，发送缓冲区满了
        // 开启对conn->SockFd() 写事件的关心
        if (!conn->OutBufferEmpty()) // 还没发完
        {
            conn->_R->EnableReadWrite(conn->SockFd(), true, true);
        }
        else
        {
            conn->_R->EnableReadWrite(conn->SockFd(), true, false);
        }
    }
    static void Excepter(Connection *conn)
    {
        INFO("connection erase done, who: %d\n", conn->SockFd());
        errno = 0;
        // 关闭connection
        conn->_R->RemoveConnection(conn->SockFd()); // 1.unordered_map 中移除 2.connection从epoll中移除对conn->SockFd()的关心
        // 关闭conn->SockFd()
        conn->Close();

        // delete conn

        delete conn;
    }
};